<?php

namespace slinks\extensions\action\configuration;

use slinks\core\DependencyInjection\IDumpsArgument;
use slinks\extensions\action\routing\Route;
use slinks\core\Config\Resource\FileResource;
/**
 * Action mapping defines the how a Given Action class will be found based upon the route and executed. 
 * The execution involves the configured method, result and interceptorStack configurations.
 * 
 * @author Navid Mitchell
 *
 */
class ActionMapping implements IActionMapping, IDumpsArgument {

    private $name;
    private $className;
    private $methodName;
    private $route;
    private $resource;
    private $resultMappings;
    private $interceptorStack;

    public function __construct($name, 
                                $className, 
                                $methodName,
                                Route $route,
                                FileResource $resource,
                                array $resultMappings, 
                                $interceptorStack = null) {
        $this->name = $name;
        $this->className = $className;
        $this->methodName = $methodName;
        $this->route = $route;
        $this->resource = $resource;
        $this->resultMappings = $resultMappings;
        $this->interceptorStack = $interceptorStack;
    }

    /**
     * The action path that this mapping is for.
     */
    public function getName() {
        return $this->name;
    }

    /**
     * @return string the class name configured for the action.
     */
    public function getClassName() {
        return $this->className;
    }

    /**
     * @return string the method name configured for the action.
     */
    public function getMethodName() {
        return $this->methodName;
    }

    /**
     * @param string $retCode
     * @return the IResultMapping object configured for the action for the result code.
     * @throws LogicException if no IResultMapping is found for the given return code.
     */
    public function getResultMapping($retCode) {
        if (!isset($this->resultMappings[$retCode])) {
            throw new \LogicException('No result mapping found for Result:' . $retCode . ' in ' . $this->className . ' for ActionPath:' . $this->name);
        }
        return $this->resultMappings[$retCode];
    }
    
    /**
     * @return the route that is configured for this ActionMapping.
     */
    public function getRoute() {
        return $this->route;
    }

    /**
     * @return slinks\core\Config\Resource\ResourceInterface get the resource that represents this IActionMapping
     */
    public function getResource() {
        return $this->resource;
    }
    
    /**
     * @return the interceptor stack to be used or null if the default should be used.
     */
    public function getInterceptorStackName() {
        return $this->interceptorStack;
    }
    
    public function setName($name) {
        $this->name = $name;
    }

    public function setClassName($className) {
        $this->className = $className;
    }

    public function setMethodName($methodName) {
        $this->methodName = $methodName;
    }

    public function setRoute($route) {
        $this->route = $route;
    }

    public function setResource($resource) {
        $this->resource = $resource;
    }

    public function setResultMappings($resultMappings) {
        $this->resultMappings = $resultMappings;
    }

    public function setInterceptorStack($interceptorStack) {
        $this->interceptorStack = $interceptorStack;
    }

    public function __clone(){
        $this->resource = clone $this->resource;
        $this->route = clone $this->route;
    } 
    
    public function getArgumentString() {
        $ret = "new slinks\\extensions\\action\\configuration\\ActionMapping('{$this->name}','{$this->className}','{$this->methodName}',{$this->getRouteString()},".
                                                                             "new slinks\\core\\Config\\Resource\\FileResource('{$this->resource->getResource()}'),".
                                                                             "array(";
        $i = 0;
        foreach ($this->resultMappings as $result) {
            if ($i > 0) {
                $ret .= ', ';
            }
            $ret .= '\'' . $result->getName() . '\'=>' . $result->getArgumentString();
            $i++;
        }
        $ret .= ') ,';
        $ret .= ( $this->interceptorStack != null ? "'{$this->interceptorStack}'" : "null");
        $ret .=')';
        return $ret;
    }
    
    private function getRouteString(){
        $route = $this->route;
        return "new slinks\\extensions\\action\\routing\\Route('{$route->getPattern()}',{$this->getArrayString($route->getDefaults())},{$this->getArrayString($route->getRequirements())},{$this->getArrayString($route->getOptions())})";
    }

    private function getArrayString($value){      
        $code = array();
        foreach ($value as $k => $v) {
            $code[] = sprintf('\'%s\' => %s', $k, (is_array($v) ? $this->getArrayString($v) : "'".$v."'"));
        }
        return sprintf('array(%s)', implode(', ', $code));
    }
    
}